package com.hup.utils.commons;

import java.util.ArrayList;

/**
 * @author hugan
 * @date 2020/3/30
 */
public class ByteUtil {


    /**
     * {@link String#indexOf(String, int)}
     */
    public static int indexOf(byte[] src, int tar, int fromIndex) {
        for(int i = fromIndex; i < src.length; i++) {
            //System.out.println(TAG + ": indexOf:"+ i+";"+src[i]);
            if(src[i] == tar) return i;
        }
        return -1;
    }

    /**
     * {@link String#indexOf(String, int)}
     * 只测试过tar.len==2
     */
    public static int indexOf(byte[] src, byte[] tar, int start) {
        if(start < 0) start = 0;
        int subCount = tar.length;
        int srcCount = src.length;
        if(subCount > 0) {
            F1:
            for(int i = start; i < srcCount; i++) {
                if(i + subCount > srcCount) {
                    return -1;
                }
                int j;
                for(j = 0; j < subCount; j++) {
                    if(src[i + j] != tar[j]) continue F1;
                }
                return i;
            }
            return -1;
        }
        return start < srcCount ? start : srcCount;
    }

    public static byte[] subBytes(byte[] src, int stIndex, int edIndex) {
        byte[] res = new byte[edIndex - stIndex];
        System.arraycopy(src, stIndex, res, 0, res.length);
        return res;
    }


    public static byte[] getBytes(String hexString) {
        if(hexString != null && hexString.length() != 0) {
            int length = hexString.length() / 2;
            char[] hexChars = hexString.toUpperCase().toCharArray();
            byte[] res = new byte[length];

            for(int i = 0; i < length; ++i) {
                int pos = i * 2;
                res[i] = (byte) (charToByte(hexChars[pos]) << 4 | charToByte(hexChars[pos + 1]));
            }

            return res;
        } else {
            return null;
        }
    }

    private static byte charToByte(char c) {
        return (byte) (c < 'A' ? (c - 48) : (c - 'A' + 10));
    }

    public static String getString(byte[] src) {
        if(src == null) return "";
        return getString(src, 0, src.length);
    }

    /**
     * @param edIndex 不含 src[edIndex]
     * @return hexString
     */
    public static String getString(byte[] src, int stIndex, int edIndex) {
        if(src == null || src.length == 0 || stIndex < 0 || edIndex <= stIndex) {
            return "";
        }
        StringBuilder sb = new StringBuilder();
        for(int i = stIndex; i < edIndex; i++) {
            byte b = src[i];
            String hex = Integer.toHexString(b & 255).toUpperCase();
            if(hex.length() == 1) sb.append("0");
            sb.append(hex);
        }
        return sb.toString();
    }

    /**
     * 只测试过tar.len==2
     */
    public static byte[] replace(byte[] src, byte[] tar, byte replacement) {
        ArrayList<Byte> lst = new ArrayList<>();
        for(int i = 0; i < src.length; i++) {
            int indexOf = indexOf(src, tar, i);
            if(indexOf == -1) {
                for(int j = i; j < src.length; j++) {
                    lst.add(src[j]);
                }
                break;
            }
            for(int j = i; j < indexOf; j++) {
                lst.add(src[j]);
            }
            lst.add(replacement);
            i = indexOf + tar.length - 1;
        }
        byte[] res = new byte[lst.size()];
        for(int i = lst.size() - 1; i >= 0; i--) {
            res[i] = lst.get(i);
        }
        return res;
    }

    public static String getString(byte b) {
        String hex = Integer.toHexString(b & 255).toUpperCase();
        if(hex.length() == 1) return "0" + hex;
        return hex;
    }

    /**
     * 根据HexChar 获取对应的数字
     *
     * @return [0, 15], or -1 if out of range
     */
    public static int getNum(char c) {
        if(c >= '0' && c <= '9') {
            return c - '0';
        }
        if(c >= 'a' && c <= 'f') {
            return c - 'a' + 10;
        }
        if(c >= 'A' && c <= 'F') {
            return c - 'A' + 10;
        }
        return -1;
    }

    /**
     * get string from integer
     * @param isUpper is toUpperCase
     * @return Integer.toHexString(i)
     */
    public static String getString(int i, boolean isUpper) {
        String hex = isUpper ? Integer.toHexString(i).toUpperCase() : Integer.toHexString(i);
        if(hex.length() % 2 == 0) return hex;
        return "0" + hex;
    }

    public static byte[] cloneByte(byte[] bytes) {
        byte[] res = new byte[bytes.length];
        System.arraycopy(bytes, 0, res, 0, res.length);
        return res;
    }
}
